/**
  ******************************************************************************
  * File Name          : produptsk.c
  * Description        : 产量数据上传
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "bsp.h"
#include "tskcfg.h"
#include "produp.h"
#include "sdiobsp.h"
#include "gv.h"
#include <string.h>

TaskHandle_t xProductionUP_Thd = NULL;
StaticTask_t xProductionUP_Tcb;
StackType_t  xProductionUP_Stk[PRODUCTIONUP_STACK_SIZE];

TaskHandle_t xProductionDB_Thd = NULL;
StaticTask_t xProductionDB_Tcb;
StackType_t  xProductionDB_Stk[PRODUCTIONDB_STACK_SIZE];

static Ethernet_FeedbackDataStru produp_rxbuf;

static Ethernet_SendQueStru produp_txbuf = {
  .sn = ETH_SOCK_NUM_PRODUP,
  .type = 1,
  .dest_ip = {192,168,6,232},
  .dest_port = 8002,
  .len = 23,
  .buf = "",
};

static volatile uint8_t tcp_connected = 0;
volatile uint8_t produp_recv_ok = 0;

static void tcp_client_connection_keeps(void)
{
  uint8_t sr;
  static TickType_t xLastWakeTime = 0;

  if(((xTaskGetTickCount() - xLastWakeTime) >= 1000) || (tcp_connected == 0))
  {
    xLastWakeTime = xTaskGetTickCount();

    sr = ethif_get_socket_sr(ETH_SOCK_NUM_PRODUP);
    switch(sr)
    {
      case SOCK_UDP:
      case SOCK_IPRAW:
      case SOCK_MACRAW:
      case SOCK_CLOSE_WAIT:
        tcp_connected = 0;
        ethif_close(ETH_SOCK_NUM_PRODUP); 

      case SOCK_CLOSED:
        tcp_connected = 0;
        ethif_socket(ETH_SOCK_NUM_PRODUP, Sn_MR_TCP, ETH_SOCK_LCPORT_PRODUP, 0);

      case SOCK_INIT:
        tcp_connected = 0;
        ethif_connect(ETH_SOCK_NUM_PRODUP, gv.hr.meas_pa.eth_produp_ip, gv.hr.meas_pa.eth_produp_port);
        break;

      case SOCK_SYNSENT:
        tcp_connected = 0;
        break;

      case SOCK_ESTABLISHED:
        tcp_connected = 1;
        break;

      default:
        break;
    }
  }
}

static void feedback_process(TickType_t blocktime)
{
  Ethernet_FeedbackCtrlStru ctrl;
  QueueSetMemberHandle_t activated_qhd;
  
  activated_qhd = xQueueSelectFromSet(produp_ethfb_qshd, blocktime);
  if(activated_qhd == produp_ethfb_qhd[CQUE])         /* 中断消息 */
  {
    if(xQueueReceive(activated_qhd, &ctrl, 0) !=NULL)
    {
      switch(ctrl.type)
      {
        case ETH_FB_CONNECTED:
          tcp_connected = 1;
          break;

        case ETH_FB_DISCONNECTED:
          tcp_connected = 0;
          break;

        case ETH_FB_TIMEOUT:
          tcp_connected = 0;
          break;

        default:
          break;
      }
    }
  }
  else if(activated_qhd == produp_ethfb_qhd[DQUE])    /* 数据消息接收 */
  {
    if(xQueueReceive(activated_qhd, &produp_rxbuf, 0) !=NULL)
    {
      if(produp_rxbuf.len >= 2){printf("OK\r\n");
        if(strstr((const char *)produp_rxbuf.buf, "OK") != NULL){
          produp_recv_ok = 1;
          memset(&produp_rxbuf, 0, sizeof(produp_rxbuf));
        }
      }
    }
  }
}

/* 产量数据库任务 */
void vProductionDB_Task(void * pvParameters)
{
  uint8_t is_realtime_data;
  uint8_t is_history_data;
  TickType_t checktick;
  Prod_DataBaseStru proddb;

  sd_detect_init();

  checktick = xTaskGetTickCount();

  while(1)
  {
    if(sd_detect_mount() == 0)  /* TODO: 如果未检测到SD卡(或故障), 会导致产量相关任务全面暂停 */
    {
      vTaskDelay(500);
      continue;
    }

    if(xQueueReceive(prod_database_qhd, &proddb, 1000) !=NULL)
    {
      proddb_save(&proddb, &is_realtime_data);
    }

    if((xTaskGetTickCount() - checktick) >= 1000)
    {
      proddb_check(&proddb, &is_history_data);
      checktick = xTaskGetTickCount();
    }

    if(is_history_data != 0)        /* 如果有历史数据 优先发历史 */
    {
      is_history_data = 0;
      
      if(produp_data_loop(&produp_txbuf, &proddb) == 0)
      {
        proddb_rcvback();
      }
      checktick = xTaskGetTickCount();
    }
    else if(is_realtime_data != 0)  /* 如果有实时数据 发实时数据 */
    {
      is_realtime_data = 0;

      if(produp_data_loop(&produp_txbuf, &proddb) == 0)
      {
        proddb_rcvback();
      }
      checktick = xTaskGetTickCount();
    }
    else
    {
      /* 无数据可发 */
    }
  }
}

/* 产量数据网络发送任务 */
void vProductionUP_Task(void * pvParameters)
{
  while(1)
  {
    tcp_client_connection_keeps();

    feedback_process(1000);
  }
}
